package com.simple.datax.seda.internal;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.simple.datax.seda.api.ConfigInfoIF;
import com.simple.datax.seda.api.SelectSourceIF;
import com.simple.datax.seda.api.SourceItemIF;
import com.simple.datax.seda.core.ObjectHolder;
import com.simple.datax.seda.core.exception.InitFailedException;
import com.simple.datax.seda.util.StringUtil;
public class LinkedSelectSource implements SelectSourceIF {

	private static final Log logger = LogFactory
			.getLog(LinkedSelectSource.class);

	private ConfigInfoIF configInfo;

	/**
	 * 包含所有加载器名称的字符串（各加载器名称之间用;分割开）
	 */
	private String sourceIndex;

	/**
	 * 最大的加载数量
	 */
	private int sourceSize = 16;

	/**
	 * 加载器,需要同步锁
	 */
	private ArrayList<SelectSourceIF> loaders = new ArrayList<SelectSourceIF>();

	/**
	 * 
	 */
	private final Object LOCKER = new Object();

	/**
	 * 已加载数量,需要同步锁
	 */
	private int currCount = 0;

	public LinkedSelectSource() {

	}

	/**
	 * 
	 * @param sourceSize
	 *            最大的加载数量
	 */
	public LinkedSelectSource(int sourceSize) {
		this.sourceSize = sourceSize;
	}

	public String getSourceId() {
		return "";
	}

	/**
	 * 
	 * @param selObj
	 *            已经处理完的业务对象
	 */
	public void deregister(Object selObj) {
		try {
			logger.debug("开始注销数据.");
			SourceItemIF item = (SourceItemIF) selObj;
			SelectSourceIF sourceUse = null;
			synchronized (LOCKER) {
				for (SelectSourceIF source : loaders) {
					if (source.getSourceId().equals(item.getSourceId())) {
						sourceUse = source;
						break;
					}
				}
			}
			if (sourceUse != null) {
				sourceUse.deregister(selObj);
			}

		} catch (Exception e) {
			logger.error("注销数据时出现异常", e);
		} finally {
			synchronized (LOCKER) {
				currCount--;
			}
		}
	}

	/**
	 * 通过加载器,加载一个DpmBizEntity实体
	 */
	public int select(ObjectHolder objectHolder) {

		logger.debug("开始加载数据.");

		synchronized (LOCKER) {
			logger.debug("源加载器数量[" + loaders.size() + "]");
			if (loaders.size() == 0)
				return SelectSourceIF.SELECT_NONE;
		}

		int remainCapacity = remainCapacity();
		if (remainCapacity <= 0) {
			logger.info("暂不加载数据,处理数量已达到上限[" + sourceSize + "]");
			return SelectSourceIF.SELECT_WOULD_BLOCK;
		}
		logger.debug("可继续加载的数量[" + remainCapacity + "]");
		// 先假设可以成功加载数据,以保证remainCapacity()可以即时生效
		// logger.debug("先假设可以成功加载数据,以保证remainCapacity()可以即时生效");
		// lockerCurrCount++;
		// if (lockerLoaders.size() == 0 && lockerClearLoaders == false) {
		// String msg = "数据加载器列表是空,请检查sourceIndex属性的设置是否正确";
		// logger.warn(msg);
		// lockerCurrCount--;
		// throw new InitFailedException(msg);
		// }
		synchronized (LOCKER) {
			logger.debug("loaders[" + loaders.size() + "]");

			for (SelectSourceIF source : loaders) {
				while (true) {
					try {
						long beginTime = System.currentTimeMillis();
						int rtn = source.select(objectHolder);
						if (rtn == SelectSourceIF.SELECT_OK) {
							logger.debug(objectHolder.value);
							long endTime = System.currentTimeMillis();
							currCount++;
							logger.info("成功加载一条数据,时间：" + (endTime - beginTime)
									+ "ms");
							return SelectSourceIF.SELECT_OK;
						} else {
							logger.debug("没有加载到数据=" + rtn);
							return rtn;
						}
					} catch (Exception e) {
						logger.error("加载一条数据失败:", e);
						// logger.error(new String(e.getErrorBytes(), "utf-8"));
						continue;
					}
				}
			}
		}
		return SelectSourceIF.SELECT_NONE;
	}

	public int remainObject() throws Exception {
		synchronized (LOCKER) {
			int count = currCount;
			for (SelectSourceIF source : loaders) {
				count += source.remainObject();
			}
			return count;
		}
	}

	public void freeze() {
		synchronized (LOCKER) {
			for (SelectSourceIF source : loaders) {
				source.freeze();
			}
		}
	}

	/**
	 * 
	 * @return 可继续加载的数量
	 */
	public int remainCapacity() {
		synchronized (LOCKER) {
			return sourceSize - currCount;
		}
	}

	/**
	 * 设置配置管理对象
	 */
	public void setCustomConfigurator(ConfigInfoIF config) {
		this.configInfo = config;
	}

	/**
	 * 设置数据加载器索引,该索引的格式是 索引1[;索引2;索引3...] 每个索引代表一个命名加载器的对象名称
	 * 
	 * @param indexStr
	 */
	public void setSourceIndex(String indexStr) {
		this.sourceIndex = indexStr;

	}

	public void initialize() throws InitFailedException {
		// logger.info("initialize");
		String[] sourceNames = StringUtil.split(this.sourceIndex, ";");
		if (sourceNames == null || sourceNames.length < 1) {
			throw new InitFailedException("加载器列表是空,请检查sourceIndex属性的设置是否正确");
		}
		synchronized (LOCKER) {
			loaders.clear();
			logger.info("加载器列表loaders清空...");
			for (int i = 0; i < sourceNames.length; i++) {
				try {
					if (sourceNames[i].trim().length() == 0) {
						continue;
					}
					// Object obj =
					// this.configInfo.getObject(sourceNames[i]);
					// System.out.println(obj.getClass().getName());

					SelectSourceIF source = (SelectSourceIF) this.configInfo
							.getObject(sourceNames[i]);
					source.setCustomConfigurator(configInfo);
					source.initialize();
					loaders.add(source);
					logger.info("加载器 sourceNames=" + sourceNames[i]);
				} catch (Exception e) {
					throw new InitFailedException("创建用户可定制数据加载器["
							+ sourceNames[i] + "]失败:" + e.getMessage());
				}
			}
		}

	}

	/**
	 * 清空各加载器的数据,并释放资源
	 */
	public void clear() {
		synchronized (LOCKER) {
			if (loaders != null) {
				Iterator<SelectSourceIF> iter = loaders.iterator();
				while (iter.hasNext()) {
					iter.next().clear();
				}
				loaders.clear();
			}
			// lockerClearLoaders = true;
		}
	}

	public void setSourceSize(int sourceSize) {
		this.sourceSize = sourceSize;
	}

}
